export enum ResponseCode {
  SUCCESS = 200,
  FAILURE = 201,
}
export enum ResponseStatus {
  SUCCESS = "success",
  FAILURE = "failed",
}

export interface WebResult<T = any> {
  time: string;
  code: ResponseCode;
  status: ResponseStatus;
  type?: ResponseStatus;
  message: string;
  data: T;
}

let baseURL = "";
const defaultHeaders: Record<string, string> = {};
export function setBaseURL(url: string) {
  baseURL = url;
}
export function setDefaultHeader(key: string, value: string) {
  defaultHeaders[key] = value;
}
export function deleteDefaultHeader(key: string) {
  delete defaultHeaders[key];
}
export function clearDefaultHeaders() {
  for (const k in defaultHeaders) {
    delete defaultHeaders[k];
  }
}

function dealRequestURL(url: string) {
  url = url.trim();
  if (!url.startsWith("http")) {
    const serverURL = baseURL.endsWith("/")
      ? baseURL.substring(0, baseURL.length - 1)
      : baseURL;
    url = url.startsWith("/") ? url : "/" + url;
    url = serverURL + url;
  }
  return url;
}

/**
 * post 方法默认使用 json 格式，
 * put、delete在存在body时使用json格式
 * @param url
 * @param options
 * @returns
 */
export function request(url: string, options: RequestInit) {
  url = dealRequestURL(url);
  options.headers = Object.assign(options.headers || {}, defaultHeaders);
  if (options.method === "POST" || options.method === "post") {
    if (options.body && !(options.body instanceof FormData)) {
      options.headers = {
        "Content-Type": "application/json",
        ...options.headers,
      };
    }
  } else if (
    options.method === "PUT" ||
    options.method === "put" ||
    options.method === "delete" ||
    options.method === "delete"
  ) {
    if (options.body && !(options.body instanceof FormData)) {
      options.headers = {
        "Content-Type": "application/json",
        ...options.headers,
      };
    }
  }
  console.log("request", url);
  return fetch(url, options);
}
export async function requestText(
  url: string,
  options: RequestInit,
): Promise<string> {
  const response = await request(url, options);
  const result = await response.text();
  console.log(`${dealRequestURL(url)} response`, result);
  return result;
}

/**
 * 请求 json
 */
export async function requestJSON(
  url: string,
  options: RequestInit,
): Promise<WebResult> {
  const response = await request(url, options);
  const result: WebResult = await response.json();
  console.log(`${dealRequestURL(url)} response`, result);
  return result;
}

export function getText(url: string, options?: RequestInit) {
  delete options?.method;
  return requestText(url, { method: "GET", ...options });
}
export function getJSON(url: string, options?: RequestInit) {
  delete options?.method;
  return requestJSON(url, { method: "GET", ...options });
}
export function postText(url: string, options: RequestInit) {
  delete options?.method;
  return requestText(url, { method: "POST", ...options });
}
export function postJSON(url: string, options: RequestInit) {
  delete options?.method;
  return requestJSON(url, { method: "POST", ...options });
}
export function putText(url: string, options?: RequestInit) {
  delete options?.method;
  return requestText(url, { method: "PUT", ...options });
}
export function putJSON(url: string, options?: RequestInit) {
  delete options?.method;
  return requestJSON(url, { method: "PUT", ...options });
}
export function deleteText(url: string, options?: RequestInit) {
  delete options?.method;
  return requestText(url, { method: "DELETE", ...options });
}
export function deleteJSON(url: string, options?: RequestInit) {
  delete options?.method;
  return requestJSON(url, { method: "DELETE", ...options });
}


export function upload(
  url: string,
  formData: FormData,
  onProgress?: (progress: number) => void,
  method?: "POST" | "PUT" | "PATCH" | "post" | "put" | "patch",
  headers?: Record<string, string>
) {
  return new Promise((resolve) => {
    url = dealRequestURL(url);
    const xhr = new XMLHttpRequest();
    xhr.open(method ? method : "POST", url);
    for(const k in defaultHeaders) {
      if (headers && headers[k]) {
        delete headers[k];
      }
      xhr.setRequestHeader(k, defaultHeaders[k]);
    }
    for (const k in headers) {
      xhr.setRequestHeader(k, headers[k]);
    }
    xhr.onload = () => {
      let res = xhr.response;
      if (!xhr.responseType) {
        try {
          res = JSON.parse(res);
        } catch (err) {
          console.error(err);
          res = xhr.response;
        }
      }
      console.log(xhr.responseType, res);
      resolve(res);
    };
    xhr.upload.onprogress = (e) => {
      const progress = e.loaded / e.total * 100;
      if (onProgress) {
        onProgress(progress);
      }
    };
    xhr.send(formData);
  });
}

export default request;
